package automaton.algorithms;

import java.util.ArrayList;
import java.util.LinkedList;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import simulator.Card;
import simulator.Point;
import simulator.Spider;
import simulator.Move;

/**
 * 
 * @author qonco
 * 
 */
public class Search {
	public static Logger log = Logger.getLogger(Search.class.getName());
	public static int bug = 0;
	public static int win = 0;
	public static int fail = 0;
	public static int total = 0;
	public static long timeSpent = 0;

	private LinkedList<Move> availabeMove = null;

	public Search() {

		PropertyConfigurator.configure("log4j.properties");

	}

	public void algorithm(int loop, int level) {
		for (int g = 0; g < loop; g++) {

			Card hold = null;

			Spider s = new Spider(level);
			// s.deal();
			int available;
			long during = 0;
			long startTime = System.currentTimeMillis();

			ENDGAME: do {
				s.deal();

				// s.show();

				available = 10;

				int deadlockCount = 0;
				int lastAvailable = 0;

				while (available > 0) {
					available = 10;
					for (int i = 0; i < 10; i++) {
						Point lastPoint = s.getLastCardLocation(i);
						if (lastPoint == null) {
							available--;
							continue;
						}

						hold = s.getMovableHeadCard(lastPoint);

						ArrayList<Point> availablePoint = s
								.availableColumn(hold);
						if (availablePoint.size() == 0) {
							// jump over
							available--;
							continue;
						} else {

							Point target = s.getMaxColumn(availablePoint);

							if (target.getY() == 0
									&& hold.getLocation().getY() == 0) {
								// if (s.getNextCard(hold) != null) {
								// s.move(s.getNextCard(hold), target);
								// }
								available--;

							} else {
								s.move(hold, target);
							}

							// s.show();

						}
					}

					log.info("available points :" + available);

					if (s.checkAllMovable() && s.getDealturn() < 60) {
						log.info("All movable. fill blank and deal.");
						s.fillBlank();
						s.deal();
						// s.show();

						if (s.checkOriginalBug()) {
							log.warn("OriginalBUG");
							bug++;
							break ENDGAME;
						}

					}

					// check deadlock
					if (lastAvailable == available) {

						deadlockCount++;

						if (deadlockCount == 21) {
							log.info("DEADLOCK!");

							if (s.getDealturn() == 60) {
								break ENDGAME;
							} else {
								continue ENDGAME;
							}

						}
					} else {
						deadlockCount = 0;

					}

					lastAvailable = available;

					long duringTime = System.currentTimeMillis();

					if (duringTime - startTime > 3000) {
						break ENDGAME;
					}

					
				}

			} while (available > 0 || s.getDealturn() < 60);

			// log.info("available  : " + available);
			// log.info("s.getDealturn()  : " + s.getDealturn());

			long endTime = System.currentTimeMillis();
			during = endTime - startTime;
			if (s.getFinish() == 8) {
				log.warn("WIN!      Total Moves: " + s.getTotalMove()
						+ ".    Time consume : " + (during) + "ms");
				timeSpent += during;
				win++;
				total++;
			} else {
				log.warn("FAIL!     Total Moves: " + s.getTotalMove()
						+ ".    Time consume : " + (during) + "ms");
				timeSpent += during;
				fail++;
				total++;
			}

		}
		log.warn(win + "/" + total + "   win/total. Catch bug: " + bug
				+ ".    Time spent : " + timeSpent / 1000 + "s.");
	}
}
